package com.common.android.utils.download.progress_updownload;

import java.io.BufferedInputStream;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import java.nio.channels.FileLock;

import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.text.TextUtils;

import com.common.android.utils.FileUtils;
import com.product.android.business.config.Configuration;
import com.product.android.utils.LogUtils;

public class ProgressDownload {
	private static final String CUR_SIZE="CUR_SIZE";
	private static final String TOTAL_SIZE="TOTAL_SIZE";
	private static final int SUCCESS=0x100;
	private static final int FAIL=0x101;
	private static final int PROGRESS=0x102;
	private IProgressListener mProgressListener;
	private boolean mIsDisconnected=false;
	public ProgressDownload(IProgressListener listener){
		mProgressListener=listener;
	}
	
	private Handler mProgressHandler=new Handler(){
		public void handleMessage(Message msg) {
			super.handleMessage(msg);
			if (mProgressListener==null){
				return;
			}
			switch (msg.what) {
			case SUCCESS:
				mProgressListener.onSuccess((String) msg.obj);
				break;
			case FAIL:
				mProgressListener.onFail((String) msg.obj);
				break;
			case PROGRESS:
				long cur=msg.getData().getLong(CUR_SIZE);
				long total=msg.getData().getLong(TOTAL_SIZE);
				mProgressListener.onProgress(cur, total);
				break;
			default:
				//do nothing
				break;
			}
		};
	};
	
	public void startDownload(final String url,final File file){
		if (TextUtils.isEmpty(url) || file==null){
			mProgressListener.onFail("null url or file");
			return;
		}
		mProgressListener.onStart();
		new Thread(new Runnable() {
			public void run() {
				fetchFile(url, file);
			}
		}).start();
	}
	
	private void fetchFile(String url,File file){
		if(null == file){
			return;
		}
		
		StringBuilder errorMsg=new StringBuilder();
		mIsDisconnected=false;
		HttpURLConnection urlConnection = null;
		BufferedInputStream in = null;
		FileOutputStream out = null;
		try {
			if (file.exists()){
				file.delete();
			}
			file.createNewFile();
			URL targetUrl = new URL(url);
			urlConnection = (HttpURLConnection) targetUrl.openConnection();
			urlConnection.addRequestProperty("CLOUDID", Configuration.CLOUNDID);
			in = new BufferedInputStream(urlConnection.getInputStream(), 8192);
			FileLock fl = null;
			FileOutputStream fos = null;
			// 获取文件大小
			// 当前下载大小
			long curSize = 0;
			long notifySize=0;
			long totalSize=urlConnection.getContentLength();
			if (totalSize<=0){
				totalSize=FileUtils.getContentLength(urlConnection);
			}
			fos = new FileOutputStream(file.getPath());
			fl = fos.getChannel().tryLock();
			if (fl != null && fl.isValid()) {
				byte[] buffer = new byte[1024 << 2];
				int len1 = 0;
				while ((len1 = in.read(buffer)) > 0) {
					if (mIsDisconnected){
						LogUtils.d("debug","network disconnected");
						fos.close();
						sendFailMessage("network disconnected");
					}
					fos.write(buffer, 0, len1);
					if (totalSize>0){
						curSize += len1;
						if (((curSize-notifySize)<<4)>totalSize){
							//当前进度增长值大于1/16，通知界面刷新一次（不需要频繁通知）
							Bundle bundle=new Bundle();
							bundle.putLong(CUR_SIZE,curSize);
							bundle.putLong(TOTAL_SIZE,totalSize);
							Message msg=mProgressHandler.obtainMessage();
							msg.what = PROGRESS;
							msg.setData(bundle);
							mProgressHandler.sendMessage(msg);
							notifySize=curSize;
						}
					}
				}
				fl.release();
				fos.close();
			}else{
				fos.close();
			}
			Message msg=mProgressHandler.obtainMessage();
			msg.obj=file.getAbsolutePath();
			msg.what=SUCCESS;
			mProgressHandler.sendMessage(msg);
		}catch (FileNotFoundException e){
			errorMsg.append("server file not found:"+url);
			if (file!=null && file.exists()){
				file.delete();
			}
			sendFailMessage(errorMsg.toString());
		}catch (Exception e) {
			errorMsg.append("Exception:"+e.getMessage());
			if (file!=null && file.exists()){
				file.delete();
			}
			sendFailMessage(errorMsg.toString());
		} finally {
			if (urlConnection != null) {
				urlConnection.disconnect();
			}
			try {
				if (out != null) {
					out.close();
				}
				if (in != null) {
					in.close();
				}
			} catch (final Exception e) {
				debug(e.getMessage());
				sendFailMessage(errorMsg.toString());
			}
		}
	}
	
	private void sendFailMessage(String error){
		Message msg=mProgressHandler.obtainMessage();
		msg.obj=error;
		msg.what=FAIL;
		mProgressHandler.sendMessage(msg);
	}
	
	protected void debug(String msg){
		LogUtils.d("debug", msg);
	}
}
